// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * mysql数据库备份工具类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年7月19日
 */
@Slf4j
public class MysqlDataBackupUtils {
    //sql文件存储的路径
    private static final String savePath = "/sql/";
    // 用户名
    private static final String username = "pmip_user";
    // 密码
    private static final String password = "Dks2022!@";
    // 导入的目标数据库所在的主机
    private static final String host = "172.30.105.178";
    // 使用的端口号
    private static final String port = "3306";
    // 导入的目标数据库的名称
    private static final String exportDatabaseName = "DKS";
    // mysql bin目录路径
    private static final String MysqlPath = getMysqlPath();

    private static final int BUFFER = 8192;

//    public static void main(String args[]){
//        String exportPath = savePath + exportDatabaseName +"_"+ DateUtil.formatDate_1(new Date()) + ".sql";
//
//        //每次处理都先删除文件
//        if(!FileUtil.deleteFolder(savePath)){
//            throw new TipsException("删除文件失败！");
//        }
//
//        File file = new File(savePath);
//        //判断文件目录是否存在
//        if(!file.exists()){
//            file.mkdirs();
//        }
//
//        //        backupAll();
////        backupTable("zip_record");
////        backupTableByWhere(exportPath, "zip_record", "activityNo='1'");
//
//        //需要备份数据的表名
//        String [] tables = { "activity""banner", "data_cul_item", "modular","user" };
//
//        backupMoreTableByWhere(exportPath, tables, "activityNo='1'");
//    }

    //根据系统判断使用mysql命令路径
    private static String getMysqlPath(){
        String osName = System.getProperty("os.name");
        if(Pattern.matches("Linux.*", osName)){
            //linux读动态库，把动态库复制到/usr/lib下
//            return "/usr/local/mysql/bin/";
            return "/usr/bin/";
        } else if (Pattern.matches("Windows.*", osName)) {
            //windows系统读动态库
            return "C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\";
        }
        return null;
    }

    /**
     * 备份全部
     *
     * @return
     */
    public static boolean backupAll(String exportPath) {
        Runtime runtime = Runtime.getRuntime();
        // 这里其实是在命令窗口中执行的 command 命令行
        try {
            StringBuffer command = new StringBuffer();
            // 注意哪些地方要空格，哪些不要空格 || 密码是用的小p，而端口是用的大P。
            command.append(MysqlPath).append("mysqldump -u").append(username).append(" -p").append(password)
                    .append(" -h").append(host).append(" -P").append(port).append(" ").append(exportDatabaseName)
                    .append(" -r ").append(exportPath);
            runtime.exec(command.toString());
            return true;
        } catch (IOException e) {
            log.error(e.toString());
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 备份数据库某个表
     * @param tableName  表名
     * @return
     */
    public static boolean backupTable(String exportPath, String tableName) {
        Runtime runtime = Runtime.getRuntime();
        // 这里其实是在命令窗口中执行的 command 命令行
        try {
            StringBuffer command = new StringBuffer();
            // 注意哪些地方要空格，哪些不要空格 || 密码是用的小p，而端口是用的大P。
            command.append(MysqlPath)
                    //账号和密码
                    .append("mysqldump -u").append(username).append(" -p").append(password)
                    //地址和端口
                    .append(" -h").append(host).append(" -P").append(port)
                    //导出数据库
                    .append(" ").append(exportDatabaseName)
                    //导出表名
                    .append(" ").append(tableName)
                    //生成文件位置
                    .append(" -r ").append(exportPath);
            runtime.exec(command.toString());
            return true;
        } catch (IOException e) {
            log.error(e.toString());
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 备份数据库某个表加条件
     *
     * @param tableName  表名
     * @param whereStr   条件字符串
     * @return 是否备份成功
     */
    public static boolean backupTableByWhere(String exportPath, String tableName, String whereStr) {
        Runtime runtime = Runtime.getRuntime();
        // 这里其实是在命令窗口中执行的 command 命令行
        try {
            StringBuffer command = new StringBuffer();
            // 注意哪些地方要空格，哪些不要空格 || 密码是用的小p，而端口是用的大P。
            command.append(MysqlPath)
                    //账号和密码
                    .append("mysqldump -u").append(username).append(" -p").append(password)
                    //地址和端口
                    .append(" -h").append(host).append(" -P").append(port)
                    //导出数据库
                    .append(" ").append(exportDatabaseName)
                    //导出表名
                    .append(" ").append(tableName)
                    //导出条件，whereStr字符串如：'id<5'
                    .append(" --where=").append(whereStr)
                    //生成文件位置
                    .append(" -r ").append(exportPath);
            runtime.exec(command.toString());
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 备份数据库多个表加条件
     *
     * @param tableNames  表名数组
     * @param whereStr   条件字符串
     * @return
     */
    public static boolean backupMoreTableByWhere(String exportPath, String [] tableNames, String whereStr) {
        Runtime runtime = Runtime.getRuntime();
        // 这里其实是在命令窗口中执行的 command 命令行
        try {
            StringBuffer command = new StringBuffer();
            // 注意哪些地方要空格，哪些不要空格 || 密码是用的小p，而端口是用的大P。
            command.append(MysqlPath);
            //账号和密码
            command.append("mysqldump -u").append(username).append(" -p").append(password);
            //地址和端口
            command.append(" -h").append(host).append(" -P").append(port);
            //导出数据库
            command.append(" ").append(exportDatabaseName);
            //导出表名
            for(String tableName : tableNames){
                command.append(" ").append(tableName);
            }
            //导出条件，whereStr字符串如：'id<5'
            command.append(" --where=").append(whereStr);
            //生成文件位置
            command.append(" -r ").append(exportPath);
            runtime.exec(command.toString());
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 压缩文件为zip
     *
     * @param filePath 文件路径
     * @param zipPath  要生成的zip压缩包路径
     */
    public static void zipFile(String filePath,String zipPath) {
        ZipOutputStream out = null;
        try {
            out = new ZipOutputStream(new FileOutputStream(zipPath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //得到文件列表信息
        File file = new File(filePath);
        // 压缩zip包
        try {
            if (!file.exists()) {
                return;
            }
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            try {

                ZipEntry entry = new ZipEntry(file.getName());
                out.putNextEntry(entry);
                int count;
                byte data[] = new byte[BUFFER];
                while ((count = bis.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }finally {
                out.closeEntry();
                bis.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        log.info("生成zip成功");
        System.out.println("生成zip成功");
    }

}
